import 'dart:async';
import 'dart:developer' as dev;

import 'package:flutter/material.dart';
import 'package:ideology/features/screens/code_editor_controller.dart';
import 'package:ideology/features/screens/widgets/editor_area/code_editor_business.dart';
import 'package:ideology/features/screens/widgets/editor_area/editor_config.dart';
import 'package:ideology/features/screens/widgets/editor_menu_bar/dialogs/new_project_dialog/new_project_dialog.dart';
import 'package:ideology/features/screens/widgets/editor_menu_bar/editor_menu_bar.dart';
import 'package:ideology/features/screens/widgets/editor_menu_bar/menu_actions.dart';
import 'package:ideology/features/screens/widgets/editor_sidebar/editor_sidebar.dart';
import 'package:ideology/features/screens/widgets/editor_sidebar/file_explorer/code_editor_explorer_action_handler.dart';
import 'package:ideology/features/screens/widgets/editor_sidebar/file_explorer/explorer_panel.dart';
import 'package:ideology/features/screens/widgets/output_panel/output_panel.dart';
import 'package:ideology/features/screens/widgets/status_bar/editor_status_bar.dart';
import 'package:ideology/features/screens/widgets/tab_bar/tab_bar.dart';
import 'package:ideology/shared/services/file_service.dart';
import 'package:ideology/shared/widgets/code_input/presentation/widgets/canvas_editor.dart';
import 'package:ideology/shared/widgets/file_explorer/file_explorer_theme_data.dart';
import 'package:ideology/shared/widgets/file_explorer/file_node.dart';
import 'package:path/path.dart' as p;

import 'code_editor_menu_action_handler.dart';

/// 整个代码编辑器的主界面（Screen）。
///
/// 功能组成：
/// - 顶部菜单栏（新建/打开/关闭/运行/调试）；
/// - 左侧窄侧边栏（切换资源管理器/输出面板）；
/// - 左侧资源管理器（可折叠、可拖动宽度）；
/// - 中间编辑区（多标签页 + 文本编辑器）；
/// - 底部输出面板（可折叠、可拖动高度）；
/// - 最底部状态栏（行/列/字符统计等）。
///
/// 内部通过 [CodeEditorController] 管理状态，
/// 并使用多个 `ValueListenableBuilder` 实现响应式 UI。
class CodeEditorScreen extends StatefulWidget {
  CodeEditorScreen({super.key})
      : controller = CodeEditorController(fileService: DefaultFileService());

  /// 编辑器核心控制器。
  final CodeEditorController controller;

  @override
  State<CodeEditorScreen> createState() => _CodeEditorScreenState();
}

class _CodeEditorScreenState extends State<CodeEditorScreen> {
  // ========= 输出面板配置 =========
  double _outputHeight = 240; // 初始高度
  static const double _outputMinHeight = 40;
  static const double _outputMaxHeight = 600;
  static const Duration _outputAnim = Duration(milliseconds: 220);

  static const double _outputHandleHeight = 10; // 拖拽手柄高度

  // ========= 资源管理器配置 =========
  double _explorerWidth = 280; // 初始宽度
  static const double _explorerMinWidth = 180;
  static const double _explorerMaxWidth = 600;
  static const Duration _explorerAnim = Duration(milliseconds: 220);

  // ========= 拖拽标记 =========
  bool _isResizingExplorer = false;
  bool _isResizingOutput = false;

  late final CodeEditorController controller = widget.controller;

  /// 编辑器业务用例集合，封装常用操作。
  late final CodeEditorUseCases useCases =
  CodeEditorUseCases(controller: controller);

  @override
  void dispose() {
    unawaited(useCases.dispose());
    super.dispose();
  }

  /// 打开项目目录。
  void _handleExplorerOpenFolder() async {
    try {
      await useCases.openProject();
    } catch (e, st) {
      dev.log('pickAndLoadProject failed', error: e, stackTrace: st);
      if (!mounted) return;
      ScaffoldMessenger.of(context)
          .showSnackBar(SnackBar(content: Text('打开项目失败: $e')));
    }
  }

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;

    // 顶部菜单动作处理器
    final menuHandler = DefaultMenuActionHandler(
      useCases: useCases,
      messenger: ScaffoldMessenger.of(context),
    );

    // 文件树动作处理器
    final explorerHandler = ExplorerActionHandler(
      useCases: useCases,
      messenger: ScaffoldMessenger.of(context),
      mounted: () => mounted,
    );

    return Scaffold(
      body: SafeArea(
        bottom: false,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            // ======= 顶部菜单栏 =======
            EditorMenuBar(
              onAction: (msg) async {
                if (msg is NewProjectData) {
                  // “新建项目”弹窗返回的数据
                  try {
                    await useCases.newProjectWith(msg);
                  } catch (e, st) {
                    dev.log('newProjectWith failed', error: e, stackTrace: st);
                    if (!mounted) return;
                    ScaffoldMessenger.of(context)
                        .showSnackBar(SnackBar(content: Text('$e')));
                  }
                  return;
                }
                final action = parseMenuAction(msg);
                if (action == null) {
                  dev.log('Unknown menu action: $msg');
                  return;
                }
                await menuHandler.handle(action);
              },
            ),

            // ========= 主工作区（侧边栏 + 编辑区 + 输出） =========
            Expanded(
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  // —— 左侧窄侧边栏（切换 Explorer / Output） ——
                  ValueListenableBuilder<bool>(
                    valueListenable: controller.showExplorer,
                    builder: (_, showExplorer, _) {
                      return ValueListenableBuilder<bool>(
                        valueListenable: controller.showOutput,
                        builder: (_, showOutput, _) {
                          return Container(
                            decoration: BoxDecoration(
                              color: cs.surface,
                              border: Border(
                                right: BorderSide(
                                  color: Theme.of(context)
                                      .dividerColor
                                      .withOpacity(0.35),
                                  width: 0.8,
                                ),
                              ),
                            ),
                            child: EditorSidebar(
                              showExplorer: showExplorer,
                              onToggleExplorer: useCases.toggleExplorer,
                              showOutput: showOutput,
                              onToggleOutput: useCases.toggleOutput,
                            ),
                          );
                        },
                      );
                    },
                  ),

                  // —— 右侧主区域：上（资源管理器 + 编辑器），下（输出面板） ——
                  Expanded(
                    child: LayoutBuilder(
                      builder: (context, parentConstraints) {
                        // 整个主区的总高度（不含顶部菜单和底部状态栏）
                        final totalHeight = parentConstraints.maxHeight;

                        // 你想让上方主区至少有多少高度（比图片tab区域下方再往下一点）
                        const double minEditorAreaHeight = 180;

                        // 输出面板最大高度（剩下空间不能小于 minEditorAreaHeight）
                        final double dynamicOutputMaxHeight =
                        (totalHeight - minEditorAreaHeight)
                            .clamp(_outputMinHeight, _outputMaxHeight);

                        return Column(
                          crossAxisAlignment: CrossAxisAlignment.stretch,
                          children: [
                            // ======= 上：资源管理器 + 编辑器 =======
                            Expanded(
                              child: Stack(
                                children: [
                                  Row(
                                    crossAxisAlignment: CrossAxisAlignment.stretch,
                                    children: [
                                      // —— 资源管理器（可折叠 + 可拖宽） ——
                                      ValueListenableBuilder<bool>(
                                        valueListenable: controller.showExplorer,
                                        builder: (_, show, _) {
                                          return AnimatedContainer(
                                            duration: _isResizingExplorer
                                                ? Duration.zero
                                                : _explorerAnim,
                                            curve: Curves.easeInOutCubic,
                                            width: show ? _explorerWidth : 0.0,
                                            decoration: BoxDecoration(
                                              color: cs.surface,
                                            ),
                                            child: ClipRect(
                                              child: IgnorePointer(
                                                ignoring: !show,
                                                child: Opacity(
                                                  opacity: show ? 1 : 0,
                                                  child: ValueListenableBuilder<
                                                      List<FileNode>>(
                                                    valueListenable:
                                                    controller.roots,
                                                    builder: (_, roots, _) {
                                                      return ExplorerPanel(
                                                        controller: controller
                                                            .explorerController,
                                                        scrollController: controller
                                                            .explorerScrollController,
                                                        onOpenFolder:
                                                        _handleExplorerOpenFolder,
                                                        roots: roots,
                                                        // 逻辑路径 → 真实路径映射
                                                        realPathResolver:
                                                            (logicalPath, node) {
                                                          final parts = logicalPath
                                                              .split('/');
                                                          if (parts.isEmpty) {
                                                            return '';
                                                          }
                                                          final rootName =
                                                              parts.first;
                                                          final base = controller
                                                              .projectRootPath;
                                                          if (base == null ||
                                                              base.trim().isEmpty) {
                                                            return '';
                                                          }
                                                          final baseName =
                                                          p.basename(base);
                                                          if (baseName !=
                                                              rootName) {
                                                            return '';
                                                          }
                                                          final rest =
                                                          parts.skip(1).toList();
                                                          final joined =
                                                          rest.isEmpty
                                                              ? base
                                                              : p.joinAll([
                                                            base,
                                                            ...rest,
                                                          ]);
                                                          return p.normalize(joined);
                                                        },
                                                        onNodeOpen: (path, node) =>
                                                            explorerHandler.openNode(
                                                              path,
                                                              node,
                                                            ),
                                                        onNodeSelect: (path, _) =>
                                                            useCases.selectPath(path),
                                                        onNodeDelete:
                                                            (path, node) async {
                                                          // 删除根目录 → 关闭项目
                                                          final isRootPath =
                                                          !path.contains('/');
                                                          final isRootFolder =
                                                              isRootPath &&
                                                                  node.isFolder;
                                                          final rootPath = controller
                                                              .projectRootPath;
                                                          bool sameAsCurrentRoot =
                                                          false;
                                                          if (node.fullPath !=
                                                              null &&
                                                              rootPath != null) {
                                                            sameAsCurrentRoot =
                                                                p.normalize(
                                                                  node.fullPath!,
                                                                ) ==
                                                                    p.normalize(
                                                                      rootPath,
                                                                    );
                                                          } else {
                                                            sameAsCurrentRoot =
                                                                isRootFolder;
                                                          }
                                                          if (sameAsCurrentRoot) {
                                                            controller
                                                                .closeCurrentProject();
                                                            controller.roots.value =
                                                            <FileNode>[];
                                                          }
                                                        },
                                                        theme:
                                                        const FileExplorerThemeData(
                                                          rowHeight: 26,
                                                        ),
                                                      );
                                                    },
                                                  ),
                                                ),
                                              ),
                                            ),
                                          );
                                        },
                                      ),

                                      // —— 编辑区（占剩余空间） ——
                                      Expanded(
                                        child: Column(
                                          crossAxisAlignment:
                                          CrossAxisAlignment.stretch,
                                          children: [
                                            TabBarWidget(controller: controller),
                                            Expanded(
                                              child: Container(
                                                color: cs
                                                    .surfaceContainerHighest,
                                                child: _buildEditorArea(),
                                              ),
                                            ),
                                          ],
                                        ),
                                      ),
                                    ],
                                  ),

                                  // —— 资源管理器拖拽手柄 ——
                                  ValueListenableBuilder<bool>(
                                    valueListenable: controller.showExplorer,
                                    builder: (_, show, _) {
                                      if (!show) return const SizedBox.shrink();
                                      return Positioned(
                                        left: _explorerWidth - 8,
                                        top: 0,
                                        bottom: 0,
                                        child: GestureDetector(
                                          behavior: HitTestBehavior.translucent,
                                          onHorizontalDragStart: (_) =>
                                              setState(() =>
                                              _isResizingExplorer = true),
                                          onHorizontalDragUpdate: (details) {
                                            setState(() {
                                              _explorerWidth = (_explorerWidth +
                                                  details.delta.dx)
                                                  .clamp(
                                                _explorerMinWidth,
                                                _explorerMaxWidth,
                                              );
                                            });
                                          },
                                          onHorizontalDragEnd: (_) => setState(
                                                  () => _isResizingExplorer = false),
                                          onHorizontalDragCancel: () => setState(
                                                  () => _isResizingExplorer = false),
                                          child: const MouseRegion(
                                            cursor: SystemMouseCursors.resizeColumn,
                                            child: SizedBox(
                                              width: 16,
                                              height: double.infinity,
                                            ),
                                          ),
                                        ),
                                      );
                                    },
                                  ),
                                ],
                              ),
                            ),

                            // ======= 下：输出面板 =======
                            ValueListenableBuilder<bool>(
                              valueListenable: controller.showOutput,
                              builder: (_, show, _) {
                                // 输出面板最大高度 = dynamicOutputMaxHeight
                                final targetHeight = show
                                    ? _outputHeight.clamp(
                                    _outputMinHeight, dynamicOutputMaxHeight)
                                    : 0.0;

                                return AnimatedContainer(
                                  duration: _isResizingOutput
                                      ? Duration.zero
                                      : _outputAnim,
                                  curve: Curves.easeInOutCubic,
                                  height: targetHeight,
                                  decoration:
                                  BoxDecoration(color: cs.surface),
                                  clipBehavior: Clip.hardEdge,
                                  child: LayoutBuilder(
                                    builder: (context, box) {
                                      final currentHeight =
                                      (box.hasBoundedHeight &&
                                          box.maxHeight.isFinite)
                                          ? box.maxHeight
                                          : 0.0;
                                      final contentVisible = currentHeight >=
                                          (_outputHandleHeight + 1.0) &&
                                          show;

                                      return Visibility(
                                        visible: contentVisible,
                                        maintainState: true,
                                        maintainAnimation: true,
                                        maintainSize: false,
                                        child: Column(
                                          children: [
                                            // —— 输出面板拖拽手柄 ——
                                            GestureDetector(
                                              behavior:
                                              HitTestBehavior.translucent,
                                              onVerticalDragStart: (_) =>
                                                  setState(() =>
                                                  _isResizingOutput = true),
                                              onVerticalDragUpdate: (details) {
                                                setState(() {
                                                  _outputHeight =
                                                      (_outputHeight -
                                                          details.delta.dy)
                                                          .clamp(
                                                        _outputMinHeight,
                                                        dynamicOutputMaxHeight,
                                                      );
                                                });
                                              },
                                              onVerticalDragEnd: (_) =>
                                                  setState(() =>
                                                  _isResizingOutput = false),
                                              onVerticalDragCancel: () =>
                                                  setState(() =>
                                                  _isResizingOutput = false),
                                              child: SizedBox(
                                                height: _outputHandleHeight,
                                                child: Stack(
                                                  alignment:
                                                  Alignment.topCenter,
                                                  children: [
                                                    Container(
                                                      height: 1,
                                                      width: double.infinity,
                                                      color: Theme.of(context)
                                                          .dividerColor
                                                          .withOpacity(0.35),
                                                    ),
                                                    const Positioned.fill(
                                                      child: MouseRegion(
                                                        cursor:
                                                        SystemMouseCursors
                                                            .resizeRow,
                                                        child: SizedBox.expand(),
                                                      ),
                                                    ),
                                                  ],
                                                ),
                                              ),
                                            ),
                                            // —— 输出面板主体 —— 绑定日志
                                            Expanded(
                                              child: OutputPanel(
                                                logs: controller.outputLines,
                                              ),
                                            ),
                                          ],
                                        ),
                                      );
                                    },
                                  ),
                                );
                              },
                            ),
                          ],
                        );
                      },
                    ),
                  ),
                ],
              ),
            ),

            // ========= 底部状态栏 =========
            EditorStatusBar(listenable: controller.status),
          ],
        ),
      ),
    );
  }

  /// 构建编辑器区域：根据当前活动 tab 渲染文本编辑器。
  Widget _buildEditorArea() {
    return ValueListenableBuilder<int>(
      valueListenable: controller.activeTabIndex,
      builder: (_, active, _) {
        if (active < 0 || active >= controller.tabs.value.length) {
          return Center(
            child: Text(
              'Open the file to start editing.',
              style: Theme.of(context).textTheme.bodyMedium?.copyWith(
                fontSize: 14,
                color: Colors.black54,
              ),
            ),
          );
        }
        final tab = controller.tabs.value[active];
        final base = editorConfig.metrics.textStyle;
        final preset = makePresetForFilename(tab.title, base);

        return CanvasEditor(
          highlighter: preset.highlighter,
          theme: preset.theme,
          externalText: tab.text,
        );
      },
    );
  }
}
